<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Allpowers BLE</title>
<script>
var writer = null, history = {},buffer = null,$ = document.querySelector.bind(document);
var device = {}, fwFile = null, deviceInfo = {
	acOpen: null,
	dcOpen: null,
	is60Hz: null,
	ledOpen: null,
	voiceOpen: null,
	canUseDay: null,
	canUseDayHour: null,
	canUseHour: null,
	canUseMinute: null,
	cycleNumber: null,
	inPower: null,
	outPower: null,
	powerAmount: null,
	sleepTime: null,
	beepOpen: null,
	screenOpen: null,
	usbOpen: null,
	ecoMode: null,
	chargingMode: null,
	acMode: null,
	carPortEn: null,
	ecoTime: null,
	chargeTime: null,
	chargeTimeHour: null,
	chargeTimeMinute: null,
	hardwareVersion: null,
	softwareVersion: null,
}, updateInfo = {
	101:"Пакет обновления был успешно загружен",
	102:"Не удалось загрузить, недостаточно места",
	103:"Ошибка загрузки, переполнение памяти",
	104:"Не удалось загрузить, время ожидания запроса на загрузку истекло",
	105:"Не удалось загрузить, разряжен аккумулятор",
	106:"Не удалось загрузить, плохой сигнал",
	107:"Ошибка загрузки, неизвестное исключение",
	201:"Успешное обновление",
	202:"Обновление не удалось, и батарея разряжена",
	203:"Ошибка обновления, переполнение памяти",
	204:"Не удалось выполнить обновление, и пакет обновления несовместим с целевой версией текущей задачи",
	205:"Не удалось выполнить обновление, не удалось выполнить проверку CRC16",
	206:"Ошибка обновления, неизвестное исключение",
	207:"Выполните максимальное количество повторных попыток (",
	208:"Срок обновления оборудования истек",
};
var params = [
	{text:"Свет",param:"ledOpen",check:"hasLedSwitch",icon:""},
	{text:"Звук",param:"beepOpen",check:"hasBuzzerSwitch",icon:""},
	{text:"Выход 220V",param:"acOpen",check:null,icon:""},
	{text:"Выход 12V",param:"dcOpen",check:null,icon:""},
	{text:"Выход USB",param:"usbOpen",check:"dcSwitchSeparate",icon:""},
];
var devices = [{
	pic: "S400",
	code: "ALLPOWERS S400",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-005",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 1,
	bleProtocolVersion: 1,
	dcSwitchSeparate: 1,
}, {
	pic: "S500",
	code: "ALLPOWERS S500",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-007",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 1,
	bleProtocolVersion: 1,
	dcSwitchSeparate: 1,
}, {
	pic: "S1000",
	code: "ALLPOWERS S1000",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-008",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 1,
	bleProtocolVersion: 1,
	dcSwitchSeparate: 1,
}, {
	pic: "S2000",
	code: "ALLPOWERS S2000",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-009",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 0,
	bleProtocolVersion: 1,
	dcSwitchSeparate: 1,
}, {
	pic: "S400",
	code: "AP S300 V2.0",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-005",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 1,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 0,
}, {
	pic: "S500",
	code: "AP S700 V2.0",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-007",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 1,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 0,
}, {
	pic: "S1000",
	code: "AP S1500 V2.0",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-008",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 1,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 0,
}, {
	pic: "S2000",
	code: "AP S2000 V2.0",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-009",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 0,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 0,
}, {
	pic: "S2000V2P",
	code: "AP S2000P V2.0",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-009 PRO",
	distributionNet: 0,
	hasMainSwitch: 1,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 0,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 0,
}, {
	pic: "R3000",
	code: "AP R600 V2.0",
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-005PRO",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 1,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 1,
}, {
	pic: "R3000",
	code: "AP R700 V2.0",
	wifiProtocolVersion: 1,
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-007PRO",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 1,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 1,
}, {
	pic: "S2000",
	code: "AP S1500MI V2.0",
	wifiProtocolVersion: 1,
	hasWifi: 0,
	hasBle: 1,
	name: "AP-SS-009MINI",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 0,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 0,
}, {
	pic: "R3000",
	code: "AP R3500 V2.0",
	wifiProtocolVersion: 1,
	hasWifi: 1,
	hasBle: 1,
	name: "AP-SS-010MAX",
	distributionNet: 1,
	hasMainSwitch: 1,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 0,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 1,
}, {
	pic: "R3000",
	code: "AP R2500 V2.0",
	wifiProtocolVersion: 1,
	hasWifi: 1,
	hasBle: 1,
	name: "AP-SS-010PRO",
	distributionNet: 0,
	hasMainSwitch: 1,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 0,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 1,
}, {
	pic: "R3000",
	code: "AP R1500 V2.0",
	wifiProtocolVersion: 1,
	hasWifi: 1,
	hasBle: 1,
	name: "AP-SS-010",
	distributionNet: 0,
	hasMainSwitch: 0,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 0,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 1,
}, {
	pic: "S4000V2",
	code: "AP R4000 V2.0",
	wifiProtocolVersion: 1,
	hasWifi: 1,
	hasBle: 1,
	name: "AP-SS-011",
	distributionNet: 0,
	hasMainSwitch: 1,
	hasBuzzerSwitch: 1,
	hasLedSwitch: 0,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 0,
}, {
	pic: "R3000",
	code: "AP B3000 V2.0",
	wifiProtocolVersion: 1,
	hasWifi: 1,
	hasBle: 1,
	name: "AP-EB-003",
	distributionNet: 1,
	hasMainSwitch: 1,
	hasBuzzerSwitch: 0,
	hasLedSwitch: 0,
	bleProtocolVersion: 2,
	dcSwitchSeparate: 1,
}
];
function setDevice(d){
$('#connect').innerHTML="Подключен к "+d.name;
for(n in devices)if(devices[n].code == d.name)device = devices[n];
device.dev = d;
device.dev.ongattserverdisconnected = function(){$('#connect').innerHTML="Соединение";device = {};writer = null;$('#device').style.display = "none";};
var html = "";
for(i in params)if(params[i].check == null || device[params[i].check] == 1)html +='<div class="param">'+params[i].text+'<span class="switch"><input id="'+params[i].param+'" type="checkbox" onchange="send({'+params[i].param+':this.checked})"/><label for="'+params[i].param+'" >Toggle</label></span></div>';
$('#params').innerHTML=html;
$('#device').style.display = "block";
}
function update(info){
Object.assign(deviceInfo,info);
for(k in info){var el = $('#'+k); if(el!=undefined)el[typeof info[k] == "boolean"?"checked":"innerHTML"] = info[k]};
}
if(Object.assign == undefined)Object.assign = function() {var o = {};for(var i=0; i < arguments.length; i += 1) {var obj = arguments[i],keys = Object.keys(obj);for(var j=0; j < keys.length; j += 1)o[keys[j]] = obj[keys[j]]}return o};
function hex_string(data){return Array.from(data).map(x=>x.toString(16).padStart(2, '0').toUpperCase()).join("-");}
function crc8(data){let crc=0xFF;for(var i=0;i<data.length;i++){crc^=data[i]&0xFF;for(var j=0;j<8;j++)if(crc & 1){crc>>=1;crc^=0xb8}else{crc>>=1}}return crc & 0xFFFF;}
function log(msg){$("#data").value=msg+"\n"+$("#data").value;}
function showConsole(x){$('#data').style.display = x?"block":"none";}
var url = x=>URL.createObjectURL(x);
function main(){
	if(navigator.bluetooth!=undefined){
		navigator.bluetooth.requestDevice({"optionalServices":['0000fff0-0000-1000-8000-00805f9b34fb'],"acceptAllDevices": true}).then(device=>device.gatt.connect())
		.then(server=>{setDevice(server.device);return server.getPrimaryService("0000fff0-0000-1000-8000-00805f9b34fb")})
		.then(service=>service.getCharacteristic("0000fff2-0000-1000-8000-00805f9b34fb"))
		.then(characterisristic=>{
			writer = characterisristic;
			log("подключен к "+characterisristic);
			return characterisristic.service;
		})
		.then(service=>service.getCharacteristic("0000fff1-0000-1000-8000-00805f9b34fb"))
		.then(characterisristic=>characterisristic.startNotifications())
		.then(characterisristic=>{
			txChar = characterisristic;
			characterisristic.oncharacteristicvaluechanged=function(e){
				let packet = new Uint8Array(e.target.value.buffer),result=device.bleProtocolVersion == 2 ? decodeNewBle(packet) : decodeOldBle(packet);
				if(result.command in [1,3])update(result);
				if(result.command == 5 && result.status == 0 && fwFile != null)
					fwFile.slice(0,result.singlePackSize).stream().getReader().read().then(x=>{
						log("Начало обновления");
						writer.writeValueWithoutResponse(x.value);
					});
				if(result.command == 5 && result.status != 0)log(result.status == 2?"Обновление запрещено на выходе устройства":"Разряженная батарея, обновления нет");
				if(result.command == 7 && fwFile != null)
					fwFile.slice(result.hasSendPackCount*result.singlePackSize,(result.hasSendPackCount+1)*result.singlePackSize).stream().getReader().read().then(x=>{
						log(result.step<=100?"Загрузка: "+result.step+"%":updateInfo[result.step]);
						writer.writeValueWithoutResponse(x.value);
					});
				log(">> "+hex_string(packet)+"   "+JSON.stringify(result));
			};
			log("ожидаем данные");
		})
		.catch(error=>{console.error(error);});
	}
}
function send(info){
	Object.assign(deviceInfo,info);
	if(writer!=null){
		var packet = device.bleProtocolVersion == 2?encodeNewBle(deviceInfo):encodeOldBle(deviceInfo);
		log("<< "+hex_string(packet)+"   "+JSON.stringify(info));
		writer.writeValueWithoutResponse(packet);
	}
}
function update_firmware(){
	var input = document.createElement('input');
	input.type = 'file';
	input.click();
	input.onchange = function(e){
		fwFile = e.target.files[0];
		writer.writeValueWithoutResponse(updateStartCommand({
			checkCode:fwFile.name,
			size: fwFile.size,
			retryTime: 5000,
			intervalTime: 10000,
		}));
	};
}
var valueAtBit = function (e, t) {return e >> t - 1 & 1},
valueAtIndex2Bit = function (e, t) { return e >> t - 1 & 3 },
crc = function(t){var a = 0;for (s = 0; s < t.length - 1; s++)0 == s ? a = t[s] : a ^= t[s];return a;},
checkCode = function(e){
	if ("string" === typeof e) return e;
	for (var t = "",n=e,i=0; i < n.length; i++){
		var r = n[i].toString(2),a = r.match(/^1+?(?=0)/);
		if (a && 8 == r.length){
			for (var s = a[0].length, o = n[i].toString(2).slice(7 - s), c = 1; c < s; c++) o += n[c + i].toString(2).slice(2);
			t += String.fromCharCode(parseInt(o,2)), i += s - 1
		} else
			t += String.fromCharCode(n[i])
	}
	return t
},
checkCodeR = function (e) {
	var t,n,i = new Array;
	t = e.length;
	for (var r = 0; r < t; r++)
		n = e.charCodeAt(r), n >= 65536 && n <= 1114111 ? (i.push(n >> 18 & 7 | 240), i.push(n >> 12 & 63 | 128), i.push(n >> 6 & 63 | 128), i.push(63 & n | 128)) : n >= 2048 && n <= 65535 ? (i.push(n >> 12 & 15 | 224), i.push(n >> 6 & 63 | 128), i.push(63 & n | 128)) : n >= 128 && n <= 2047 ? (i.push(n >> 6 & 31 | 192), i.push(63 & n | 128)) : i.push(255 & n);
	return i
},
decodeOldBle = function(e){
	var s = 256 * e[8] + e[9];
	return {
		dcOpen: 1 == valueAtBit(e[0], 1),
		usbOpen: 1 == valueAtBit(e[0], 2),
		acOpen: 1 == valueAtBit(e[0], 3),
		ledOpen: 1 == valueAtBit(e[0], 4),
		isLowElectric: 1 == valueAtBit(e[0], 5),
		is60Hz: 1 == valueAtBit(e[0], 6),
		powerAmount: e[1],
		inPower: 256 * e[2] + e[3],
		outPower: 256 * e[4] + e[5],
		cycleNumber: 256 * e[6] + e[7],
		canUseDay: Math.floor(s / 60 / 24),
		canUseDayHour: Math.floor(s / 60 % 24),
		canUseHour: Math.floor(s / 60),
		canUseMinute: s % 60
	};
},encodeOldBle = function (e) {
	var t = "00";
	t += e.is60Hz ? "1" : "0",
	t += "0",
	t += e.ledOpen ? "1" : "0",
	t += e.acOpen ? "1" : "0",
	t += e.usbOpen ? "1" : "0",
	t += e.dcOpen ? "1" : "0";
	var d = new Uint8Array([187,parseInt(t, 2)]);
	return d;
},decodeNewBle = function(e){
	if (e[0] != 0xa5 || e[1] != 0x65 || e[5]+8 != e.length || e[e.length - 1] != crc(e))
		return log("Ошибка в принятом сообщении"),{};
	switch(e[6]){
	case 1:
		var s = 256 * e[13] + e[14];
		return {
			command: e[6],
			dcOpen: 1 == valueAtBit(e[7], 1),
			acOpen: 1 == valueAtBit(e[7], 2),
			is60Hz: 1 == valueAtBit(e[7], 3),
			beepOpen: 1 == valueAtBit(e[7], 4),
			ledOpen: 1 == valueAtBit(e[7], 5),
			screenOpen: 1 == valueAtBit(e[7], 6),
			voiceOpen: 1 == valueAtBit(e[7], 7),
			powerAmount: e[8],
			inPower: 256 * e[9] + e[10],
			outPower: 256 * e[11] + e[12],
			canUseDay: Math.floor(s / 60 / 24),
			canUseDayHour: Math.floor(s / 60 % 24),
			canUseHour: Math.floor(s / 60),
			canUseMinute: s % 60
		};
	case 3:
		return {
			command: e[6],
			ecoMode: 1 == valueAtBit(e[7], 1),
			chargingMode: valueAtIndex2Bit(e[7], 2),
			acMode: 1 == valueAtBit(e[7], 4),
			carPortEn: 1 == valueAtBit(e[7], 5),
			ecoTime: e[8],
			chargeTime: 256 * e[9] + e[10],
			chargeTimeHour: Math.floor(256 * e[9] + e[10] / 60),
			chargeTimeMinute: 256 * e[9] + e[10] % 60,
			hardwareVersion: e[11].toString(16) / 10,
			softwareVersion: e[12].toString(16) / 10
		};
	case 5:
		return {
			command: e[6], status: e[7],
			singlePackSize: 256 * e[8] + e[9],
			cutPackCount: 256 * e[10] + e[11]
		};
	case 7:
		return {
			command: e[6], step: e[7],
			singlePackSize: 256 * e[8] + e[9],
			hasSendPackCount: 256 * e[10] + e[11],
			checkCode: checkCode([e[12], e[13]])
		};
	default:
		return {
			command: e[6],
		};
	}
},encodeNewBle = function (e) {
	var t = e.voiceOpen ? "1" : "0"
	t += e.screenOpen ? "1" : "0",
	t += e.ledOpen ? "1" : "0",
	t += e.beepOpen ? "1" : "0",
	t += e.is60Hz ? "1" : "0",
	t += e.closeBle ? "1" : "0",
	t += e.acOpen ? "1" : "0",
	t += e.dcOpen ? "1" : "0";
	var d = new Uint8Array([0xA5,0x65,0,0xB1,1,1,0,parseInt(t, 2),0]);
	d[8] = crc(d);
	return d;
},updateStartCommand = function (e) {
	var i = checkCodeR(e.checkCode);
	var d = new Uint8Array([
		0xA5,0x65,0,0xB1,1,2,4,
		Math.floor(e.size / 16777216),
		Math.floor(e.size / 65536) % 256,
		Math.floor(e.size / 256) % 256,
		e.size % 256,
		e.retryTime,
		e.intervalTime,
		i[0],i[1],0
	]);
	d[15]=crc(d);
	return d
},serviceSendToDeviceNewModelStatus = function(e){
	var t = "000";
	t += e.carPortEn ? "1" : "0",
	t += e.acMode ? "1" : "0",
	0 == e.chargingMode ? t += "00" : 1 == e.chargingMode ? t += "01" : 2 == e.chargingMode && (t += "10");
	t += e.ecoMode ? "1" : "0";
	var d = new Uint8Array([0xA5,0x65,0,0xB1,1,2,2,parseInt(d, 2),e.ecoTime,0]);
	d[9] = crc(d);
	return d;
};
</script>
<style>
body {
	margin:0;
	background:#FFFFFF;
	font-family: Helvetica, Arial, sans-serif;
}
#menu {width:auto;display:block;text-align:left;line-height:1.2;}
#menu ul {display:block;margin:0;padding:0;position:relative;width:auto;font-size:0;text-align:left;color:#EEE;background-color:#333;border:transparent;list-style:none;z-index:999999990;border-radius: 3px;}
#menu li {display:inline-block;position:relative;font-size:0;margin:0;padding:0;}
#menu >ul>li>span, #menu >ul>li>a {font-size:12px;color:inherit;text-decoration:none;padding:10px 15px;font-weight:400;text-transform:uppercase;letter-spacing:2px;display:block;position:relative;transition:all 0.3s;}
#menu li:hover > span, #menu li:hover > a {color:#333;background-color:#F3F3F3;}
#menu .smenu {text-align:left;left:0;color: #333;background-color:#F3F3F3;border:none;position:absolute;box-shadow: 0 4px 8px rgba(0,0,0,0.3);display:none;opacity:0;cursor:default;}
#menu .smenu li {display: block;}
#menu .smenu li > span, #menu .smenu li > a {font-size:14px;font-weight:400;font-family:inherit;margin:0;padding:8px 20px; display:block;color:inherit;text-decoration:none;}
#menu .smenu li:hover > span, #menu .smenu li:hover > a{color:#333;background-color:#DDD;}
#menu .smenu li > .smenu.right0 {left:auto;right:100%;}
#menu li:hover > .smenu {display:block;opacity:1;z-index:1;}
#menu .smenu li > .smenu {left:100%; right:auto;top:0;}
#menu ul.smenu {min-width:240px;}
#menu div.smenu {text-align:center;}
#menu .arrow {color:inherit;border-style:solid; border-width:2px 2px 0 0; padding:4px; transform:rotate(135deg);margin-top:-8.5px;margin-left:4px;position:relative;display: inline-block;width: 0;height: 0;vertical-align:middle;overflow:hidden;}
#menu .smenu .arrow {transform:rotate(45deg);top:50%;margin-top:-6px;position:absolute;left:auto;right:20px;}
@keyframes topItemAnimation {from {opacity: 0; transform:translate3d(0, -60px, 0);} to {opacity: 1; transform:translate3d(0, 0, 0);}}
#menu li a {animation:none;}
#menu.active li a { animation: topItemAnimation 0.5s cubic-bezier(.16,.84,.44,1) 0.083s backwards;}
#menu.active li:nth-of-type(1) a { animation: topItemAnimation 0.5s cubic-bezier(.16,.84,.44,1) 0.5s backwards;}
#menu.active li:nth-of-type(2) a { animation: topItemAnimation 0.5s cubic-bezier(.16,.84,.44,1) 0.41s backwards;}
#menu.active li:nth-of-type(3) a { animation: topItemAnimation 0.5s cubic-bezier(.16,.84,.44,1) 0.33s backwards;}
#menu.active li:nth-of-type(4) a { animation: topItemAnimation 0.5s cubic-bezier(.16,.84,.44,1) 0.25s backwards;}
#menu.active li:nth-of-type(5) a { animation: topItemAnimation 0.5s cubic-bezier(.16,.84,.44,1) 0.16s backwards;}@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { #menu.active li a{animation:none!important;}}
.switch input[type=checkbox]{height:0;width:0;visibility:hidden;}
.switch label{cursor: pointer;text-indent: -9999px;width: 40px;height:20px;background:grey;display:block;border-radius:20px;position:relative;}
.switch label:after {content:'';position:absolute;top:1px;left:1px;width:18px;height:18px;background:#fff;border-radius:18px;transition: 0.3s;}
.switch input:checked + label {background: #bada55;}
.switch input:checked + label:after {left: calc(100% - 1px);transform: translateX(-100%);}
.switch label:active:after {width: 26px;}
.param {font-size: 28px;padding: 10px;margin: 20px;border: 1px dotted #555;border-radius: 10px;}
.data {font-size: 28px;padding: 10px;}
.param .switch {float: right;}
#params { float: left; padding: 20px }
#data {position:absolute;bottom: 0px;left:0px;width: 100vw;height: 120px;}
</style>
</head>
<body>
<div id="menu">
	<ul>
		<li>
			<span>Устройство <i class="arrow"></i></span>
			<ul class="smenu">
				<li><a href="javascript:main()" id="connect">Соединение</a></li>
				<li><span>Свет <i class="arrow"></i></span>
					<ul class="smenu">
						<li><a href="javascript:send({ledOpen:true})">Включить</a></li>
						<li><a href="javascript:send({ledOpen:false})">Отключить</a></li>
					</ul>
				</li>
				<li><span>Выход 220V <i class="arrow"></i></span>
					<ul class="smenu">
						<li><a href="javascript:send({acOpen:true})">Включить</a></li>
						<li><a href="javascript:send({acOpen:false})">Отключить</a></li>
					</ul>
				</li>
				<li><span>Выход 12V/USB <i class="arrow"></i></span>
					<ul class="smenu">
						<li><a href="javascript:send({dcOpen:true})">Включить</a></li>
						<li><a href="javascript:send({dcOpen:false})">Отключить</a></li>
					</ul>
				</li>
				<li><span>Консоль отладки <i class="arrow"></i></span>
					<ul class="smenu">
						<li><a href="javascript:showConsole(false)">Скрыть</a></li>
						<li><a href="javascript:showConsole(true)">Показать</a></li>
					</ul>
				</li>
				<li><a href="javascript:update_firmware()">Обновление прошивки</a></li>
			</ul>
		</li>
	</ul>
</div>
<div id="device" style="display:none;">
<div class="data"><span id="canUseHour"></span>:<span id="canUseMinute"></span></div>
<div class="data">Заряд: <span id="powerAmount"></span>%</div>
<div class="data">Питание: <span id="inPower"></span>W</div>
<div class="data">Отдача: <span id="outPower"></span>W</div>
<div id="params"></div></div>
<textarea id="data" style="display: none;" rows=20 cols=50></textarea>

</body>
</html>